home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / NR3.C < prev    next >
C/C++ Source or Header  |  1990-07-25  |  35KB  |  1,203 lines

  1. /* NET/ROM level 3 low level processing */
  2.  
  3. #include <stdio.h>
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "iface.h"
  7. #include "trace.h"
  8. #include "timer.h"
  9. #include "arp.h"
  10. #include "slip.h"
  11. #include "ax25.h"
  12. #include "netrom.h"
  13. #include "lapb.h"
  14. #include "ip.h"
  15. #include <ctype.h>
  16.  
  17. struct nrnbr_tab *nrnbr_tab[NRNUMCHAINS];
  18. struct nrroute_tab *nrroute_tab[NRNUMCHAINS];
  19. struct nrnf_tab *nrnf_tab[NRNUMCHAINS];
  20. struct ax25_call *nr_excl[NHASH];
  21.  
  22. /* netrom level 3 params */
  23. unsigned nr_autofloor = 1;
  24. unsigned nr_maxfail = 1;
  25. unsigned nr_maxqueue = 16;
  26. unsigned nr_maxroutes = 3;
  27. unsigned nr_nfmode = NRNF_NOFILTER;
  28. unsigned nr_tcpip = NRT_NORM;
  29. unsigned nr_ttl = 10;
  30. unsigned obso_init = 6;
  31. unsigned obso_minbc = 5;
  32. char nr_aliasip[] = NR_TCPIP;
  33.  
  34. struct interface *nr_interface;
  35. struct ax25_addr nr_nodebc;
  36.  
  37. static struct nrnf_tab *find_nrnf();
  38. static struct ax25_addr *find_nbrif ();
  39. static int alt_route();
  40.  
  41. /* Send datagrams across a NET/ROM network connection */
  42. void
  43. nr_send3(bp,dest)
  44. struct mbuf *bp;
  45. struct ax25_addr *dest;
  46.  
  47. {
  48.     struct nr3hdr n3hdr;
  49.     void nr__route();
  50.  
  51.     n3hdr.source.call[0] = '\0';    /* source call to be filled in */
  52.     memcpy(&n3hdr.dest,dest,sizeof(struct ax25_addr));
  53.     n3hdr.ttl = nr_ttl;
  54.  
  55.     nr__route(&n3hdr,bp,NULLAXADDR);/* pass off to level 3 routing code */
  56. }
  57.  
  58. /* Figure out if a call is assigned to one of my NET/ROM
  59.  * interfaces.
  60.  */
  61. int
  62. ismycall(addr)
  63. struct ax25_addr *addr;
  64. {
  65.     register struct interface *ifp;
  66.  
  67.     if (nr_interface != NULLIF && nr_interface->hwaddr != NULLCHAR)
  68.         return addreq((struct ax25_addr *)(nr_interface->hwaddr),addr);
  69.  
  70.     for (ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
  71.         if (ifp->nriface != NULLNRIFACE &&
  72.         addreq((struct ax25_addr *)(ifp->hwaddr),addr)) {
  73.         return 1;
  74.         }
  75.  
  76.     return 0;
  77. }
  78.  
  79. /* Determine the netrom source call to be used (global or interface) */
  80. struct ax25_addr *
  81. nr_scall (ifp)
  82. struct interface *ifp;
  83.  
  84. {
  85.     if (nr_interface->hwaddr != NULLCHAR)
  86.         return (struct ax25_addr *)nr_interface->hwaddr;
  87.     else
  88.         return (struct ax25_addr *)ifp->hwaddr;
  89. }
  90.  
  91. /* Route NET/ROM network layer packets.
  92.  * This function is called for NET/ROM packets incoming on AX.25 interfaces.
  93.  */
  94. void
  95. nr_route(axp,bp)
  96. struct ax25_cb *axp;            /* receiving AX.25 connection */
  97. struct mbuf *bp;            /* incoming NET/ROM packet */
  98. {
  99.     struct nr3hdr n3hdr;
  100.     int i;
  101.     char *cp,*putaxaddr();
  102.     struct nrroute_tab *rp;
  103.     char neighbor[3 * AXALEN];
  104.  
  105.     if (axp->interface->nriface == NULLNRIFACE ||    /* not NET/ROM iface? */
  106.         !ismycall(&axp->addr.source) ||        /* bad call? */
  107.         ntohnr3(&n3hdr,&bp) < 0 ||            /* header bad? */
  108.         valid_addr(&n3hdr.source) != 0) {        /* illegal source? */
  109.         free_p(bp);
  110.         return;
  111.     }
  112.  
  113.     /* a real NET/ROM does not like to be polled using I(P) frames */
  114.     /* set the pthresh to zero when a connection apparently is from */
  115.     /* a NET/ROM neighbor, to prevent trouble. we will use RR(P). */
  116.  
  117.     axp->pthresh = 0;
  118.  
  119.     /* when filtermode "exclusive" is selected, we only want to route */
  120.     /* netrom traffic from nodes in our filter table. check if the */
  121.     /* callsign sending the packet (axp->addr.dest) is in the table. */
  122.  
  123.     if (nr_nfmode == NRNF_EXCLUSIVE &&
  124.         find_nrnf(&axp->addr.dest,axp->interface) == NULLNRNFTAB) {
  125.         free_p(bp);        /* not in list, discard packet */
  126.         return;
  127.     }
  128.  
  129.     /* when we receive something from a node, be certain a route */
  130.     /* exists to that node. if not, create a route from information */
  131.     /* in the incoming packet.  this is done to make sure a retour */
  132.     /* route exists when a response packet has to be sent. */
  133.  
  134.     if (((rp = find_nrroute(&n3hdr.source)) == NULLNRRTAB ||
  135.         rp->routes == NULLNRBIND || rp->routes->quality == 0) &&
  136.         !ismycall(&n3hdr.source) &&
  137.         axp->addr.ndigis < 3)        /* required by NET/ROM... */
  138.     {
  139.         cp = putaxaddr(neighbor,&axp->addr.dest);
  140.         for (i = 0; i < axp->addr.ndigis; i++){
  141.             cp[-1] &= ~E;
  142.             cp = putaxaddr(cp,&axp->addr.digis[i]);
  143.         }
  144.         cp[-1] |= E;
  145.  
  146.         nr_rt_add(NULLCHAR,        /* don't know alias */
  147.               &n3hdr.source,    /* dest=source node from l3 hdr */
  148.               axp->interface,    /* receiving interface */
  149.               1,            /* a low quality (but >0) */
  150.               obso_init,
  151.               neighbor,        /* path to source */
  152.               0);            /* treat like broadcast info */
  153.     }
  154.  
  155.     nr__route(&n3hdr,bp,&axp->addr.dest);
  156. }
  157.  
  158. /* Same, but header already extracted */
  159. /* Used by nr_route(), and also for outgoing NET/ROM packets. */
  160. void
  161. nr__route(hdr,bp,source)
  162. struct nr3hdr *hdr;
  163. struct mbuf *bp;
  164. struct ax25_addr *source;
  165. {
  166.     struct ax25_cb *axp,*find_ax25(),*open_ax25();
  167.     struct ax25 naxhdr;
  168.     struct ax25_addr neighbor,*scall;
  169.     struct mbuf *hbp,*pbp;
  170.     register struct nrnbr_tab *np;
  171.     register struct nrroute_tab *rp;
  172.     int route_tries;
  173.     extern int16 axwindow;
  174. #ifdef OLD_NETROM
  175.     unsigned char nr4head[NR4HLEN];
  176. #endif
  177.     void ax_incom(),nr3_state();
  178.  
  179.     /* check if the packet is addressed to one of our NET/ROM calls */
  180.     /* if so, bump it up to either NET/ROM level 4, or to IP */
  181.     if (ismycall(&hdr->dest)) {
  182.         /* trace input from "netrom" fake interface */
  183.         dump(nr_interface,IF_TRACE_IN,TRACE_NETROM,bp);
  184.  
  185.         /* check if it is from me.    if so, it is a routing loop! */
  186.         if (hdr->source.call[0] == '\0' || ismycall(&hdr->source)){
  187.         free_p(bp);
  188.         return;
  189.         }
  190.  
  191. #ifdef OLD_NETROM
  192.         /* these statements check if the packet is a NET/ROM transport
  193.            layer packet, or an IP packet passed over the NET/ROM network
  194.            layer. checks applied are:
  195.            - first byte does not look like an IP Version/IHL byte
  196.            - byte 4 is a valid NET/ROM transport layer opcode
  197.            boy is this awful! who invented this way of sending IP
  198.            packets over NET/ROM???!!
  199.            fortunately, a new method is to use NET/ROM opcode 0 to
  200.            encapsulate an IP packet. the old one is still preserved
  201.            in the name of backward-compatability. (if OLD_NETROM defined)
  202.          */
  203.         if (pullup(&bp,nr4head,NR4HLEN) != NR4HLEN)
  204.         return;            /* very small packet, cannot be valid */
  205.         if ((hbp = pushdown(bp,NR4HLEN)) == NULLBUF){ /* put the header back on */
  206.         free_p(bp);
  207.         return;
  208.         }
  209.         memcpy(hbp->data,nr4head,NR4HLEN);
  210.         if ((nr4head[0] & 0xf0) != (IPVERSION << 4) &&
  211.         (nr4head[4] & NR4OMASK) <= NR4INFACK){
  212.         nr4recv(hbp);        /* send to NET/ROM transport */
  213.         } else {
  214.         ip_route(hbp,0);    /* it may be an IP packet */
  215.         }
  216. #else
  217.         nr4recv(bp);        /* always send to NET/ROM transport */
  218. #endif
  219.         return;
  220.     }
  221.  
  222.     if (--(hdr->ttl) == 0) {  /* the packet's time to live is over! */
  223.         free_p(bp);
  224.         return;
  225.     }
  226.  
  227.     if ((rp = find_nrroute(&hdr->dest)) == NULLNRRTAB) {
  228.         /* no route, drop the packet */
  229.         free_p(bp);
  230.         return;
  231.     }
  232.  
  233.     route_tries = nr_maxroutes;
  234.  
  235.     while (route_tries)
  236.     {
  237.         if (rp->routes == NULLNRBIND) {
  238.         /* This shouldn't happen yet, but might if we add */ 
  239.         /* dead route detection */
  240.         free_p(bp);
  241.         return;
  242.         }
  243.  
  244.         np = rp->routes->via;
  245.         getaxaddr(&neighbor,np->call);
  246.  
  247.         /* check if we are going to send the packet back to the neighbor */
  248.         /* that just sent it to us. if so, there apparently exists no */
  249.         /* usable route to the destination from there, and we better try */
  250.         /* an alternative route */
  251.  
  252.         if (source != NULLAXADDR && addreq(source,&neighbor)){
  253.         if (alt_route(rp) < 0)        /* one route only */
  254.             break;
  255.  
  256.         route_tries--;
  257.         } else {
  258.         break;
  259.         }
  260.     }
  261.  
  262.     scall = nr_scall(np->interface);    /* get netrom call */
  263.  
  264.     /* Now check to see if the source call is null.     That is */
  265.     /* a signal from nr_send that the packet originates here,*/
  266.     /* so we need to insert the callsign of the appropriate     */
  267.     /* interface.  this will be the global NET/ROM callsign     */
  268.     /* if available, else the callsign for the interface     */
  269.     if (hdr->source.call[0] == '\0')
  270.         memcpy(&hdr->source,scall,AXALEN);
  271.  
  272.     /* Make sure there is a connection to the neighbor */
  273.     if ((axp = find_ax25(&neighbor,scall)) == NULLAX25 ||
  274.         (axp->state != CONNECTED && axp->state != SETUP)) {
  275.         /* Open a new connection or reinitiali